unit dorm.Filters;

interface

uses
  Rtti,
  TypInfo,
  Generics.Collections;

type

  TdormCompareOperator = (coEqual, coGreaterThan, coLowerThan, coGreaterOrEqual,
    coLowerOrEqual, coNotEqual, coLike);
  TdormLogicRelation = (lrAnd, lrOr);

  IdormSearchCriteria = interface
    ['{7F19727A-8113-43F0-8211-A3EFB47E57EB}']
    function GetSQL: string;
    function GetItemClassInfo: PTypeInfo;
  end;

  TdormParam = class
  public
    Value: TValue;
  end;

  TdormParameters = class(TObjectList<TdormParam>)

  end;

  TdormCriteriaItem = class
  private
    FCompareOperator: TdormCompareOperator;
    FAttribute: string;
    FValue: TValue;
    FLogicRelation: TdormLogicRelation;
    procedure SetAttribute(const Value: string);
    procedure SetCompareOperator(const Value: TdormCompareOperator);
    procedure SetValue(const Value: TValue);
    procedure SetLogicRelation(const Value: TdormLogicRelation);
  public
    property Attribute: string read FAttribute write SetAttribute;
    property CompareOperator: TdormCompareOperator read FCompareOperator
      write SetCompareOperator;
    property Value: TValue read FValue write SetValue;
    property LogicRelation: TdormLogicRelation read FLogicRelation
      write SetLogicRelation;
  end;

  TdormCriteria = class(TdormCriteriaItem)
  private
    FItems: TObjectList<TdormCriteriaItem>;
    function Add(Criteria: TdormCriteria; LogicRelation: TdormLogicRelation): TdormCriteria; overload;
    function Add(const Attribute: string; CompareOperator: TdormCompareOperator; Value: TValue;
      LogicRelation: TdormLogicRelation = lrAnd): TdormCriteria; overload;
  public
    constructor Create; overload; virtual;
    constructor Create(const Attribute: string; CompareOperator: TdormCompareOperator;
      Value: TValue); overload; virtual;
    constructor Create(Criteria: TdormCriteria); overload; virtual;
    destructor Destroy; override;
    procedure Clear;
    function AddOr(const Attribute: string; CompareOperator: TdormCompareOperator; Value: TValue)
      : TdormCriteria; overload;
    function AddAnd(const Attribute: string; CompareOperator: TdormCompareOperator; Value: TValue)
      : TdormCriteria; overload;
    function AddOr(Criteria: TdormCriteria): TdormCriteria; overload; deprecated 'Use _OR Instead';
    function AddAnd(Criteria: TdormCriteria): TdormCriteria; overload; deprecated 'Use _AND Instead';
    function _Or(Criteria: TdormCriteria): TdormCriteria; overload;
    function _Or(const Attribute: string; CompareOperator: TdormCompareOperator;
      Value: TValue): TdormCriteria; overload;
    function _And(Criteria: TdormCriteria): TdormCriteria; overload;
    function _And(const Attribute: string; CompareOperator: TdormCompareOperator;
      Value: TValue): TdormCriteria; overload;
    function Count: Integer;
    function GetCriteria(const index: Integer): TdormCriteriaItem;
    class function NewCriteria(const Attribute: string; CompareOperator: TdormCompareOperator;
      Value: TValue): TdormCriteria; overload;
    class function NewCriteria(Criteria: TdormCriteria): TdormCriteria; overload;
  end;

  TdormSimpleSearchCriteria = class(TInterfacedObject, IdormSearchCriteria)
  protected
    FSQL: string;
    FItemClassInfo: PTypeInfo;
  public
    constructor Create(AItemClassInfo: PTypeInfo; ASQL: string); virtual;
    function GetSQL: string;
    function GetItemClassInfo: PTypeInfo;
  end;

  TdormSearch = class(TdormSimpleSearchCriteria)
  private
    FParameters: TdormParameters;
  public
    constructor Create(AItemClassInfo: PTypeInfo; ASQL: string); override;
    destructor Destroy; override;
    property Parameters: TdormParameters read FParameters;
  end;

function NewCriteria(Criteria: TdormCriteria): TdormCriteria; overload;
function NewCriteria(const Attribute: string; CompareOperator: TdormCompareOperator;
  Value: TValue): TdormCriteria; overload;

implementation

uses
  dorm.Commons,
  dorm.Utils;

function NewCriteria(Criteria: TdormCriteria): TdormCriteria;
begin
  Result := TdormCriteria.NewCriteria(Criteria);
end;

function NewCriteria(const Attribute: string; CompareOperator: TdormCompareOperator;
  Value: TValue)
  : TdormCriteria;
begin
  Result := TdormCriteria.NewCriteria(Attribute, CompareOperator, Value);
end;

{ TdormSimpleSearchCriteria }

constructor TdormSimpleSearchCriteria.Create(AItemClassInfo: PTypeInfo;
  ASQL: string);
begin
  inherited Create;
  FSQL := ASQL;
  FItemClassInfo := AItemClassInfo;
end;

function TdormSimpleSearchCriteria.GetItemClassInfo: PTypeInfo;
begin
  Result := FItemClassInfo;
end;

function TdormSimpleSearchCriteria.GetSQL: string;
begin
  Result := FSQL;
end;

{ TdormCriteria }

{ TdormCriteria }

function TdormCriteria.Add(const Attribute: string; CompareOperator: TdormCompareOperator;
  Value: TValue; LogicRelation: TdormLogicRelation): TdormCriteria;

var
  Item: TdormCriteriaItem;
begin
  Item := TdormCriteriaItem.Create;
  Item.Attribute := Attribute;
  Item.CompareOperator := CompareOperator;
  Item.Value := Value;
  Item.LogicRelation := LogicRelation;
  FItems.Add(Item);
  Result := Self;
end;

function TdormCriteria.AddAnd(Criteria: TdormCriteria): TdormCriteria;
begin
  Result := _And(Criteria);
end;

function TdormCriteria.AddOr(const Attribute: string; CompareOperator: TdormCompareOperator;
  Value: TValue): TdormCriteria;
begin
  Result := _Or(Attribute, CompareOperator, Value);
end;

function TdormCriteria.Add(Criteria: TdormCriteria; LogicRelation: TdormLogicRelation)
  : TdormCriteria;

var
  Item: TdormCriteriaItem;
begin
  Item := Criteria;
  Item.LogicRelation := LogicRelation;
  FItems.Add(Item);
  Result := Self;
end;

function TdormCriteria.AddAnd(const Attribute: string; CompareOperator: TdormCompareOperator;
  Value: TValue): TdormCriteria;
begin
  Result := _And(Attribute, CompareOperator, Value);
end;

procedure TdormCriteria.Clear;
begin
  FItems.Clear;
end;

function TdormCriteria.Count: Integer;
begin
  Result := FItems.Count;
end;

constructor TdormCriteria.Create(Criteria: TdormCriteria);
begin
  Create;
  Add(Criteria, lrAnd);
end;

constructor TdormCriteria.Create(const Attribute: string; CompareOperator: TdormCompareOperator;
  Value: TValue);
begin
  Create;
  Add(Attribute, CompareOperator, Value);
end;

constructor TdormCriteria.Create;
begin
  inherited;
  FItems := TObjectList<TdormCriteriaItem>.Create(true);
end;

destructor TdormCriteria.Destroy;
begin
  FItems.Free;
  inherited;
end;

function TdormCriteria.GetCriteria(const index: Integer): TdormCriteriaItem;
begin
  Result := FItems[index];
end;

class function TdormCriteria.NewCriteria(Criteria: TdormCriteria): TdormCriteria;
begin
  Result := TdormCriteria.Create;
  Result.Add(Criteria, lrAnd);
end;

function TdormCriteria._And(Criteria: TdormCriteria): TdormCriteria;
begin
  Result := Add(Criteria, lrAnd);
end;

function TdormCriteria._Or(Criteria: TdormCriteria): TdormCriteria;
begin
  Result := Add(Criteria, lrOr);
end;

class function TdormCriteria.NewCriteria(const Attribute: string;
  CompareOperator: TdormCompareOperator; Value: TValue): TdormCriteria;
begin
  Result := TdormCriteria.Create;
  Result.Add(Attribute, CompareOperator, Value);
end;

function TdormCriteria.AddOr(Criteria: TdormCriteria): TdormCriteria;
begin
  Result := _Or(Criteria);
end;

function TdormCriteria._And(const Attribute: string; CompareOperator: TdormCompareOperator;
  Value: TValue): TdormCriteria;
begin
  Result := Add(Attribute, CompareOperator, Value, lrAnd);
end;

function TdormCriteria._Or(const Attribute: string; CompareOperator: TdormCompareOperator;
  Value: TValue): TdormCriteria;
begin
  Result := Add(Attribute, CompareOperator, Value, lrOr);
end;

{ TdormSearch }

constructor TdormSearch.Create(AItemClassInfo: PTypeInfo; ASQL: string);
begin
  inherited;
  FParameters := TdormParameters.Create(true);
end;

destructor TdormSearch.Destroy;
begin
  FParameters.Free;
  inherited;
end;

procedure TdormCriteriaItem.SetAttribute(const Value: string);
begin
  FAttribute := Value;
end;

procedure TdormCriteriaItem.SetCompareOperator(const Value
  : TdormCompareOperator);
begin
  FCompareOperator := Value;
end;

procedure TdormCriteriaItem.SetLogicRelation(const Value: TdormLogicRelation);
begin
  FLogicRelation := Value;
end;

procedure TdormCriteriaItem.SetValue(const Value: TValue);
begin
  FValue := Value;
end;

end.
